#include "fastcgi++/log.hpp"
#include "fastcgi++/fcgistreambuf.hpp"

#include <ostream>
#include <algorithm>
#include <iostream>
#include <string>

unsigned called;

const Fastcgipp::Protocol::FcgiId FCGIID = 2006;

void checker(const Fastcgipp::Socket& socket, Fastcgipp::Block&& record)
{
    if(record.size() % Fastcgipp::Protocol::chunkSize)
        FAIL_LOG("Our record is not sized properly");

    const Fastcgipp::Protocol::Header& header
        = *reinterpret_cast<Fastcgipp::Protocol::Header*>(record.begin());

    if(header.fcgiId != FCGIID)
        FAIL_LOG("Our FcgiId doesn't match")

    if(header.version != Fastcgipp::Protocol::version)
        FAIL_LOG("FastCGI version not set properly")

    if(header.type != Fastcgipp::Protocol::RecordType::OUT)
        FAIL_LOG("FastCGI record type wrong")

    switch(called)
    {
        case 0:
        {
            const unsigned char body[] =
            {
                0x49, 0x6e, 0x20, 0x62, 0x6f, 0x74, 0x61, 0x6e, 0x79, 0x2c,
                0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x69, 0x73,
                0x20, 0x61, 0x20, 0x70, 0x65, 0x72, 0x65, 0x6e, 0x6e, 0x69,
                0x61, 0x6c, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x77,
                0x69, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x6c, 0x6f,
                0x6e, 0x67, 0x61, 0x74, 0x65, 0x64, 0x20, 0x73, 0x74, 0x65,
                0x6d, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x75, 0x6e,
                0x6b, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
                0x69, 0x6e, 0x67, 0x20, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68,
                0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x61,
                0x76, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x6f, 0x73,
                0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x2e,
                0x20, 0x49, 0x6e, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x75,
                0x73, 0x61, 0x67, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65,
                0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f,
                0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
                0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x6e,
                0x61, 0x72, 0x72, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x69,
                0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f,
                0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x79, 0x20,
                0x70, 0x6c, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74,
                0x68, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
                0x79, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2c, 0x20,
                0x70, 0x6c, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61,
                0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x61, 0x62,
                0x6c, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6c, 0x75, 0x6d, 0x62,
                0x65, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6c, 0x61, 0x6e,
                0x74, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61,
                0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64,
                0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x54,
                0x72, 0x65, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e,
                0x6f, 0x74, 0x20, 0x61, 0x20, 0x74, 0x61, 0x78, 0x6f, 0x6e,
                0x6f, 0x6d, 0x69, 0x63, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70,
                0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
                0x64, 0x65, 0x20, 0x61, 0x20, 0x76, 0x61, 0x72, 0x69, 0x65,
                0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x6c, 0x61, 0x6e,
                0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x20,
                0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
                0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
                0x74, 0x6c, 0x79, 0x20, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x65,
                0x64, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x79, 0x20,
                0x74, 0x72, 0x75, 0x6e, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20,
                0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x20, 0x61,
                0x73, 0x20, 0x61, 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x6f,
                0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x61, 0x62, 0x6f,
                0x76, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70,
                0x6c, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63,
                0x6f, 0x6d, 0x70, 0x65, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72,
                0x20, 0x73, 0x75, 0x6e, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e,
                0x20, 0x49, 0x6e, 0x20, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x72,
                0x20, 0x73, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x74,
                0x68, 0x65, 0x20, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20,
                0x70, 0x61, 0x6c, 0x6d, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65,
                0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x66, 0x65, 0x72, 0x6e,
                0x73, 0x2c, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x73,
                0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x6d, 0x62, 0x6f,
                0x6f, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x73,
                0x6f, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x2e, 0x20, 0x54,
                0x72, 0x65, 0x65, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x64, 0x20,
                0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x6f, 0x6e, 0x67,
                0x2d, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x73, 0x6f,
                0x6d, 0x65, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x69, 0x6e,
                0x67, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x20,
                0x74, 0x68, 0x6f, 0x75, 0x73, 0x61, 0x6e, 0x64, 0x20, 0x79,
                0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2e, 0x20,
                0x54, 0x68, 0x65, 0x20, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x73,
                0x74, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x72,
                0x65, 0x65, 0x2c, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x61, 0x73,
                0x74, 0x20, 0x72, 0x65, 0x64, 0x77, 0x6f, 0x6f, 0x64, 0x20,
                0x6e, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x48, 0x79, 0x70, 0x65,
                0x72, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x6e,
                0x64, 0x73, 0x20, 0x31, 0x31, 0x35, 0x2e, 0x36, 0x20, 0x6d,
                0x20, 0x28, 0x33, 0x37, 0x39, 0x20, 0x66, 0x74, 0x29, 0x20,
                0x68, 0x69, 0x67, 0x68, 0x2e, 0x20, 0x54, 0x72, 0x65, 0x65,
                0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65,
                0x6e, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74,
                0x65, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x33,
                0x37, 0x30, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x6f, 0x6e,
                0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e, 0x20, 0x49, 0x74,
                0x20, 0x69, 0x73, 0x20, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
                0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
                0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6a,
                0x75, 0x73, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x33,
                0x20, 0x74, 0x72, 0x69, 0x6c, 0x6c, 0x69, 0x6f, 0x6e, 0x20,
                0x6d, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x72, 0x65,
                0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
                0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x0a, 0x0a, 0xd0, 0x94,
                0xd0, 0xb5, 0xcc, 0x81, 0xd1, 0x80, 0xd0, 0xb5, 0xd0, 0xb2,
                0xd0, 0xbe, 0x20, 0x28, 0xd0, 0xbb, 0xd0, 0xb0, 0xd1, 0x82,
                0x2e, 0x20, 0xc3, 0xa1, 0x72, 0x62, 0x6f, 0x72, 0x29, 0x20,
                0xe2, 0x80, 0x94, 0x20, 0xd0, 0xb6, 0xd0, 0xb8, 0xd0, 0xb7,
                0xd0, 0xbd, 0xd0, 0xb5, 0xd0, 0xbd, 0xd0, 0xbd, 0xd0, 0xb0,
                0xd1, 0x8f, 0x20, 0xd1, 0x84, 0xd0, 0xbe, 0xd1, 0x80, 0xd0,
                0xbc, 0xd0, 0xb0, 0x20, 0xd0, 0xb4, 0xd0, 0xb5, 0xd1, 0x80,
                0xd0, 0xb5, 0xd0, 0xb2, 0xd1, 0x8f, 0xd0, 0xbd, 0xd0, 0xb8,
                0xd1, 0x81, 0xd1, 0x82, 0xd1, 0x8b, 0xd1, 0x85, 0x20, 0xd1,
                0x80, 0xd0, 0xb0, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xb5, 0xd0,
                0xbd, 0xd0, 0xb8, 0xd0, 0xb9, 0x20, 0xd1, 0x81, 0x20, 0xd0,
                0xb5, 0xd0, 0xb4, 0xd0, 0xb8, 0xd0, 0xbd, 0xd1, 0x81, 0xd1,
                0x82, 0xd0, 0xb2, 0xd0, 0xb5, 0xd0, 0xbd, 0xd0, 0xbd, 0xd0,
                0xbe, 0xd0, 0xb9, 0x2c, 0x20, 0xd0, 0xbe, 0xd1, 0x82, 0xd1,
                0x87, 0xd1, 0x91, 0xd1, 0x82, 0xd0, 0xbb, 0xd0, 0xb8, 0xd0,
                0xb2, 0xd0, 0xbe, 0x20, 0xd0, 0xb2, 0xd1, 0x8b, 0xd1, 0x80,
                0xd0, 0xb0, 0xd0, 0xb6, 0xd0, 0xb5, 0xd0, 0xbd, 0xd0, 0xbd,
                0xd0, 0xbe, 0xd0, 0xb9, 0x2c, 0x20, 0xd0, 0xbc, 0xd0, 0xbd,
                0xd0, 0xbe, 0xd0, 0xb3, 0xd0, 0xbe, 0xd0, 0xbb, 0xd0, 0xb5,
                0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb5, 0xd0, 0xb9, 0x2c, 0x20,
                0xd0, 0xb2, 0x20, 0xd1, 0x80, 0xd0, 0xb0, 0xd0, 0xb7, 0xd0,
                0xbd, 0xd0, 0xbe, 0xd0, 0xb9, 0x20, 0xd1, 0x81, 0xd1, 0x82,
                0xd0, 0xb5, 0xd0, 0xbf, 0xd0, 0xb5, 0xd0, 0xbd, 0xd0, 0xb8,
                0x20, 0xd0, 0xbe, 0xd0, 0xb4, 0xd1, 0x80, 0xd0, 0xb5, 0xd0,
                0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd0, 0xbd, 0xd0, 0xb5, 0xd0,
                0xb2, 0xd1, 0x88, 0xd0, 0xb5, 0xd0, 0xb9, 0x2c, 0x20, 0xd1,
                0x81, 0xd0, 0xbe, 0xd1, 0x85, 0xd1, 0x80, 0xd0, 0xb0, 0xd0,
                0xbd, 0xd1, 0x8f, 0xd1, 0x8e, 0xd1, 0x89, 0xd0, 0xb5, 0xd0,
                0xb9, 0xd1, 0x81, 0xd1, 0x8f, 0x20, 0xd0, 0xb2, 0x20, 0xd1,
                0x82, 0xd0, 0xb5, 0xd1, 0x87, 0xd0, 0xb5, 0xd0, 0xbd, 0xd0,
                0xb8, 0xd0, 0xb5, 0x20, 0xd0, 0xb2, 0xd1, 0x81, 0xd0, 0xb5,
                0xd0, 0xb9, 0x20, 0xd0, 0xb6, 0xd0, 0xb8, 0xd0, 0xb7, 0xd0,
                0xbd, 0xd0, 0xb8, 0x2c, 0x20, 0xd1, 0x80, 0xd0, 0xb0, 0xd0,
                0xb7, 0xd0, 0xb2, 0xd0, 0xb5, 0xd1, 0x82, 0xd0, 0xb2, 0xd0,
                0xbb, 0xd1, 0x91, 0xd0, 0xbd, 0xd0, 0xbd, 0xd0, 0xbe, 0xd0,
                0xb9, 0x20, 0x28, 0xd0, 0xba, 0xd1, 0x80, 0xd0, 0xbe, 0xd0,
                0xbc, 0xd0, 0xb5, 0x20, 0xd0, 0xbf, 0xd0, 0xb0, 0xd0, 0xbb,
                0xd1, 0x8c, 0xd0, 0xbc, 0x29, 0x20, 0xd0, 0xb3, 0xd0, 0xbb,
                0xd0, 0xb0, 0xd0, 0xb2, 0xd0, 0xbd, 0xd0, 0xbe, 0xd0, 0xb9,
                0x20, 0xd0, 0xbe, 0xd1, 0x81, 0xd1, 0x8c, 0xd1, 0x8e, 0x20,
                0xe2, 0x80, 0x94, 0x20, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xb2,
                0xd0, 0xbe, 0xd0, 0xbb, 0xd0, 0xbe, 0xd0, 0xbc, 0x2e, 0x0a,
                0x0a, 0xeb, 0x82, 0x98, 0xeb, 0xac, 0xb4, 0xeb, 0x8a, 0x94,
                0x20, 0xeb, 0x82, 0x98, 0xeb, 0xac, 0xb4, 0xec, 0xa7, 0x88,
                0xeb, 0xa1, 0x9c, 0x20, 0xeb, 0x90, 0x9c, 0x20, 0xec, 0xa4,
                0x84, 0xea, 0xb8, 0xb0, 0xeb, 0xa5, 0xbc, 0x20, 0xea, 0xb0,
                0x80, 0xec, 0xa7, 0x80, 0xea, 0xb3, 0xa0, 0x20, 0xec, 0x9e,
                0x88, 0xeb, 0x8a, 0x94, 0x20, 0xec, 0x97, 0xac, 0xeb, 0x9f,
                0xac, 0xed, 0x95, 0xb4, 0xec, 0x82, 0xb4, 0xec, 0x9d, 0xb4,
                0x20, 0xec, 0x8b, 0x9d, 0xeb, 0xac, 0xbc, 0xec, 0x9d, 0xb4,
                0xeb, 0x8b, 0xa4, 0x2e, 0x20, 0xeb, 0xaa, 0xa9, 0xeb, 0xb3,
                0xb8, 0x28, 0xe6, 0x9c, 0xa8, 0xe6, 0x9c, 0xac, 0x29, 0x2c,
                0x20, 0xeb, 0xaa, 0xa9, 0xeb, 0xb3, 0xb8, 0x20, 0xec, 0x8b,
                0x9d, 0xeb, 0xac, 0xbc, 0x28, 0xe6, 0x9c, 0xa8, 0xe6, 0x9c,
                0xac, 0xe6, 0xa4, 0x8d, 0xe7, 0x89, 0xa9, 0x29, 0xec, 0x9d,
                0xb4, 0xeb, 0x9d, 0xbc, 0xea, 0xb3, 0xa0, 0xeb, 0x8f, 0x84,
                0x20, 0xed, 0x95, 0x9c, 0xeb, 0x8b, 0xa4, 0x2e, 0x0a, 0x0a,
                0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20,
                0x26, 0x71, 0x75, 0x6f, 0x74, 0x3b, 0xd1, 0x80, 0xd0, 0xb0,
                0xd0, 0xb7, 0xd0, 0xbd, 0xd0, 0xbe, 0xd0, 0xb9, 0x26, 0x71,
                0x75, 0x6f, 0x74, 0x3b, 0x20, 0x26, 0x6c, 0x74, 0x3b, 0x73,
                0x68, 0x6f, 0x75, 0x6c, 0x64, 0x26, 0x67, 0x74, 0x3b, 0x20,
                0x62, 0x65, 0x20, 0x26, 0x61, 0x6d, 0x70, 0x3b, 0x48, 0x54,
                0x4d, 0x4c, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64,
                0x20, 0x26, 0x61, 0x70, 0x6f, 0x73, 0x3b, 0xec, 0x97, 0xac,
                0xeb, 0x9f, 0xac, 0xed, 0x95, 0xb4, 0xec, 0x82, 0xb4, 0xec,
                0x9d, 0xb4, 0x26, 0x61, 0x70, 0x6f, 0x73, 0x3b, 0x2e, 0x0a,
                0x0a, 0x41, 0x6e, 0x64, 0x25, 0x32, 0x30, 0x74, 0x68, 0x69,
                0x73, 0x25, 0x32, 0x30, 0x70, 0x61, 0x72, 0x74, 0x25, 0x32,
                0x31, 0x25, 0x32, 0x30, 0x25, 0x32, 0x32, 0xd1, 0x84, 0xd0,
                0xbe, 0xd1, 0x80, 0xd0, 0xbc, 0xd0, 0xb0, 0x25, 0x32, 0x37,
                0x25, 0x32, 0x30, 0x25, 0x35, 0x42, 0x73, 0x68, 0x6f, 0x75,
                0x6c, 0x64, 0x25, 0x35, 0x44, 0x25, 0x32, 0x30, 0x25, 0x32,
                0x33, 0x62, 0x65, 0x25, 0x32, 0x30, 0x25, 0x33, 0x46, 0x55,
                0x52, 0x4c, 0x25, 0x33, 0x46, 0x25, 0x32, 0x30, 0x25, 0x32,
                0x46, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x25, 0x32,
                0x46, 0x25, 0x32, 0x43, 0x25, 0x32, 0x30, 0x62, 0x75, 0x74,
                0x25, 0x32, 0x34, 0x25, 0x32, 0x42, 0x25, 0x33, 0x44, 0x25,
                0x32, 0x36, 0x25, 0x32, 0x30, 0x74, 0x68, 0x65, 0x72, 0x65,
                0x25, 0x32, 0x30, 0x61, 0x72, 0x65, 0x25, 0x32, 0x30, 0x25,
                0x34, 0x30, 0x6d, 0x61, 0x6e, 0x79, 0x25, 0x33, 0x41, 0x25,
                0x33, 0x42, 0x25, 0x32, 0x30, 0x25, 0x32, 0x38, 0x6d, 0x6f,
                0x72, 0x65, 0x25, 0x32, 0x39, 0x25, 0x32, 0x30, 0x25, 0x32,
                0x41, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x25, 0x32,
                0x30, 0x74, 0x6f, 0x25, 0x32, 0x30, 0x25, 0x33, 0x43, 0x74,
                0x65, 0x73, 0x74, 0x25, 0x33, 0x45, 0x25, 0x32, 0x30, 0x6f,
                0x75, 0x74, 0x25, 0x32, 0x35, 0x2e
            };
            static const char* const bodyStart =
                reinterpret_cast<const char*>(body);
            static const char* const bodyEnd =
                reinterpret_cast<const char*>(body+sizeof(body));

            if(!std::equal(
                        bodyStart,
                        bodyEnd,
                        record.begin()+sizeof(header),
                        record.begin()+sizeof(header)+header.contentLength))
                FAIL_LOG("Our body isn't right on try " << called);

            break;
        }

        case 1:
        {
            const std::string body("And some more words.");

            if(!std::equal(
                        body.cbegin(),
                        body.cend(),
                        record.begin()+sizeof(header),
                        record.begin()+sizeof(header)+header.contentLength))
                FAIL_LOG("Our body isn't right on try " << called);

            break;

        }

        case 2:
        {
            const std::string body("Let's try some dumping.");

            if(!std::equal(
                        body.cbegin(),
                        body.cend(),
                        record.begin()+sizeof(header),
                        record.begin()+sizeof(header)+header.contentLength))
                FAIL_LOG("Our body isn't right on try " << called);

            break;

        }

        case 3:
        {
            const std::string body("Last words!");

            if(!std::equal(
                        body.cbegin(),
                        body.cend(),
                        record.begin()+sizeof(header),
                        record.begin()+sizeof(header)+header.contentLength))
                FAIL_LOG("Our body isn't right on try " << called);

            break;

        }

        case 4:
        {

        const std::string body("In botany, a tree is a perennial plant with an "
            "elongated stem, "
            "or trunk, supporting branches and leaves in most species. In some "
            "usages, the definition of a tree may be narrower, including only "
            "woody plants with secondary growth, plants that are usable as "
            "lumber or plants above a specified height. Trees are not a "
            "taxonomic group but include a variety of plant species that have "
            "independently evolved a woody trunk and branches as a way to tower"
            " above other plants to compete for sunlight. In looser senses, the"
            " taller palms, the tree ferns, bananas and bamboos are also trees."
            " Trees tend to be long-lived, some reaching several thousand years"
            " old. The tallest known tree, a coast redwood named Hyperion, "
            "stands 115.6 m (379 ft) high. Trees have been in existence for 370"
            " million years. It is estimated that there are just over 3 "
            "trillion mature trees in the world.");

            if(!std::equal(
                        body.cbegin(),
                        body.cend(),
                        record.begin()+sizeof(header),
                        record.begin()+sizeof(header)+header.contentLength))
                FAIL_LOG("Our body isn't right on try " << called);

            break;
        }
    }

    record.clear();
    ++called;
}

int main()
{
    using Fastcgipp::Encoding;
    called = 0;

    // Testing with wide characters
    {
        Fastcgipp::FcgiStreambuf<wchar_t> streambuf;
        streambuf.configure(
                Fastcgipp::Protocol::RequestId(
                    FCGIID,
                    Fastcgipp::Socket()),
                Fastcgipp::Protocol::RecordType::OUT,
                checker);

        std::basic_ostream<wchar_t> out(&streambuf);
        out << "In botany, a tree is a perennial plant with an elongated stem, "
            "or trunk, supporting branches and leaves in most species. In some "
            "usages, the definition of a tree may be narrower, including only "
            "woody plants with secondary growth, plants that are usable as "
            "lumber or plants above a specified height. Trees are not a "
            "taxonomic group but include a variety of plant species that have "
            "independently evolved a woody trunk and branches as a way to tower"
            " above other plants to compete for sunlight. In looser senses, the"
            " taller palms, the tree ferns, bananas and bamboos are also trees."
            " Trees tend to be long-lived, some reaching several thousand years"
            " old. The tallest known tree, a coast redwood named Hyperion, "
            "stands 115.6 m (379 ft) high. Trees have been in existence for 370"
            " million years. It is estimated that there are just over 3 "
            "trillion mature trees in the world.\n\n";

        out << L"Де́рево (лат. árbor) — жизненная форма деревянистых растений с "
            "единственной, отчётливо выраженной, многолетней, в разной степени "
            "одревесневшей, сохраняющейся в течение всей жизни, разветвлённой "
            "(кроме пальм) главной осью — стволом.\n\n";

        out << L"나무는 나무질로 된 줄기를 가지고 있는 여러해살이 식물이다. "
        "목본(木本), 목본 식물(木本植物)이라고도 한다.\n\n";

        out << Encoding::HTML << L"This part \"разной\" <should> be &HTML "
            "escaped '여러해살이'." << Encoding::NONE << "\n\n";

        out << Encoding::URL << L"And this part! \"форма' [should] #be ?URL? "
            "/encoded/, but$+=& there are @many:; (more) *symbols to <test> "
            "out%." << Encoding::NONE;

        out.flush();

        out << "And some more words.";

        std::string string("Let's try some dumping.");

        streambuf.dump(string.data(), string.size());

        out << "Last words!";
    }

    // Testing with narrow characters
    {
        Fastcgipp::FcgiStreambuf<char> streambuf;
        streambuf.configure(
                Fastcgipp::Protocol::RequestId(
                    FCGIID,
                    Fastcgipp::Socket()),
                Fastcgipp::Protocol::RecordType::OUT,
                checker);

        std::basic_ostream<char> out(&streambuf);
        out << "In botany, a tree is a perennial plant with an elongated stem, "
            "or trunk, supporting branches and leaves in most species. In some "
            "usages, the definition of a tree may be narrower, including only "
            "woody plants with secondary growth, plants that are usable as "
            "lumber or plants above a specified height. Trees are not a "
            "taxonomic group but include a variety of plant species that have "
            "independently evolved a woody trunk and branches as a way to tower"
            " above other plants to compete for sunlight. In looser senses, the"
            " taller palms, the tree ferns, bananas and bamboos are also trees."
            " Trees tend to be long-lived, some reaching several thousand years"
            " old. The tallest known tree, a coast redwood named Hyperion, "
            "stands 115.6 m (379 ft) high. Trees have been in existence for 370"
            " million years. It is estimated that there are just over 3 "
            "trillion mature trees in the world.";
    }

    if(called != 5)
        FAIL_LOG("Our checker() was not called as many times as it should have")
    return 0;
}
